package gui

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
	"github.com/go-git/go-git/v5"

	"git-hawk/internal/logic/models"
	"git-hawk/internal/logic/services"
)

type MainWindow struct {
	Version  string
	Apps     fyne.App
	Window   fyne.Window
	Services *services.Application
	//git仓库列表
	RepositoryList map[string]*RepositoryInfo

	//当前选中节点和上次选中节点不一样时，才刷新
	CurrentSelectUID string
}
type RepositoryInfo struct {
	Repo *git.Repository
	//已暂存文件
	StoredFilesList []string
	//未暂存文件
	NotStoredFilesList []string
}

// 列表索引(用于显示左侧列表)
var dataIndex map[string][]string

// 在 gui 包中
func NewMainWindow(apps fyne.App, win fyne.Window) *MainWindow {
	return &MainWindow{
		Apps:     apps,
		Window:   win,
		Services: &services.Application{Win: win},
		// 其他初始化
	}
}

var topWindow fyne.Window

var tree *widget.Tree

// 列表数据
var TreeTabData = make(map[string]services.TreeTabInfo)

var setTreeTab func(t services.TreeTabInfo)

func (ui *MainWindow) MakeUI() fyne.CanvasObject {
	content := container.NewStack()
	setTreeTab = func(t services.TreeTabInfo) {
		if fyne.CurrentDevice().IsMobile() {
			child := ui.Apps.NewWindow(t.Info.Name)
			topWindow = child
			child.SetContent(t.View(topWindow))
			child.Show()
			child.SetOnClosed(func() {
				topWindow = ui.Window
			})
			return
		}

		content.Objects = []fyne.CanvasObject{t.View(ui.Window)}
		content.Refresh()
	}

	// rightUiLayout := container.NewBorder(container.NewVBox(title, widget.NewSeparator()), nil, nil, nil, content)
	rightUiLayout := container.NewBorder(nil, nil, nil, nil, content)

	// 调用 makeTreeTab 函数获取 fyne.CanvasObject 实例
	treeTab := ui.makeTreeTab(setTreeTab)
	// 创建水平分割容器
	allLayout := container.NewHSplit(treeTab, rightUiLayout)
	allLayout.Offset = 0.20
	return container.NewBorder(nil, nil, nil, nil, allLayout)
}

// 创建主菜单
func (ui *MainWindow) CreateMenuItems() {

	exportMenuItem := fyne.NewMenuItem("导出", func() {

	})

	fileMenu := fyne.NewMenu("文件", exportMenuItem)

	addTplItem := fyne.NewMenuItem("添加模板", func() {})
	toolMenu := fyne.NewMenu("工具", addTplItem)

	processDocMenuItem := fyne.NewMenuItem("文档", func() {

	})

	aboutMenuItem := fyne.NewMenuItem("关于", func() {
		window := fyne.CurrentApp().NewWindow("pass tree")
		content := "版本: " + ui.Version + "\n" + "作者: Raymond工作室\n"
		window.SetContent(widget.NewLabel(content))
		window.Resize(fyne.NewSize(200, 100))
		window.Show()
	})
	helpMenu := fyne.NewMenu("帮助", processDocMenuItem, aboutMenuItem)

	menu := fyne.NewMainMenu(fileMenu, toolMenu, helpMenu)

	ui.Window.SetMainMenu(menu)
}

// 创建左侧树形菜单
func (ui *MainWindow) makeTreeTab(setTreeTab func(treeTab services.TreeTabInfo)) fyne.CanvasObject {

	dataIndex = ui.GetList()

	tree = widget.NewTree(
		func(id widget.TreeNodeID) []widget.TreeNodeID {
			return dataIndex[id]
		},
		func(id widget.TreeNodeID) bool {
			_, exists := dataIndex[id]
			return exists && len(dataIndex[id]) > 0
		},
		func(branch bool) fyne.CanvasObject {
			return widget.NewLabel("Template")
		},
		func(id widget.TreeNodeID, branch bool, node fyne.CanvasObject) {
			label := node.(*widget.Label)
			label.SetText("📁 " + id)

		},
	)
	tree.OnSelected = func(uid string) {
		// fmt.Println("Tree node selected:", uid)
		if uid == "首页" {
			if t, ok := TreeTabData[uid]; ok {
				setTreeTab(t)
			}
			return
		}
		//当前选中节点和上次选中节点不一样时，才刷新
		ui.CurrentSelectUID = uid
		// 获取工作树
		worktree, err := ui.RepositoryList[uid].Repo.Worktree()
		if err != nil {
			fmt.Printf("获取工作树失败: %v\n", err)
			os.Exit(1)
		}
		// log.Println("当前工作树:", worktree.Filesystem.Root())

		/* branchName := "develop"
		// 检查分支是否存在
		ref, err := ui.RepositoryList[uid].Repo.Reference(plumbing.ReferenceName("refs/heads/"+branchName), false)
		if err != nil {
			// return fmt.Errorf("分支 %s 不存在: %v", branchName, err)
		}
		// 切换分支
		err = worktree.Checkout(&git.CheckoutOptions{
			Branch: ref.Name(),
			Force:  true, // 强制切换，忽略未提交的更改（谨慎使用）
		})
		if err != nil {
			// return fmt.Errorf("切换分支失败: %v", err)
		}
		fmt.Println("当前分支:", ref.Name()) */

		// 获取状态
		status, err := worktree.Status()
		if err != nil {
			fmt.Printf("获取状态失败: %v\n", err)
			// 尝试重置索引
			err = worktree.Reset(&git.ResetOptions{Mode: git.MixedReset})
			if err != nil {
				fmt.Printf("重置失败: %v\n", err)
				os.Exit(1)
			}
		}

		/* // 打印未暂存更改
		if err := printUnstagedChanges(worktree); err != nil {
			fmt.Println(err)
		}

		// 打印修改的文件
		fmt.Println("修改的文件:")
		/* //查看工作树中已修改但未暂存的文件
		for file, fileStatus := range status {
			// if fileStatus.Worktree != ' ' { // ' ' 表示无变化
			// 	// fmt.Printf("%s: %s\n", file, fileStatus.Worktree)
			// 	fmt.Println(file)
			// }
			// ui.RepositoryList[uid].StoredFilesList = append(ui.RepositoryList[uid].StoredFilesList, file)

			// 正确判断未暂存的修改文件
			if fileStatus.Worktree != git.Unmodified && fileStatus.Staging == git.Unmodified {
				fmt.Println(file)
				// 过滤掉.git目录下的文件和其他不需要的文件
				if !strings.HasPrefix(file, ".git/") && !shouldIgnoreFile(file) {
					fmt.Println(file)
					ui.RepositoryList[uid].StoredFilesList = append(ui.RepositoryList[uid].StoredFilesList, file)
				}
			}
		} */
		// hasUnstagedChanges := false

		for file, fileStatus := range status {
			// 检查 Worktree 字段是否有变化（非空格字符）
			// 同时排除已暂存但工作树无变化的情况（Staging 有变化但 Worktree 无变化）
			// if fileStatus.Worktree != ' ' && (fileStatus.Staging == ' ' || fileStatus.Worktree != fileStatus.Staging) {
			/* if fileStatus.Worktree != ' ' && fileStatus.Staging == ' ' {
			hasUnstagedChanges = true
			// fmt.Printf("- %s: %s\n", path, fileStatus.Worktree.String())
			fmt.Printf("- %s: \n", path)
			} */
			fmt.Println("Worktree:", fileStatus.Worktree)
			fmt.Println("Staging:", fileStatus.Staging)

			/* fmt.Printf("- %s: \n", path) */

			// 仅显示已跟踪文件的变更（排除未跟踪文件）
			/*
				if fileStatus.Worktree != ' ' &&
					(fileStatus.Staging == ' ' || fileStatus.Worktree != fileStatus.Staging) {
					fmt.Printf("- %s:\n", path)
				}
			*/
			/*
				if isUntracked(fileStatus) {
					fmt.Println(path)
				}
			*/

			if checkFileStatus(file, fileStatus) {
				//已暂存
				ui.RepositoryList[uid].StoredFilesList = append(ui.RepositoryList[uid].StoredFilesList, file)
			} else {
				//未暂存
				ui.RepositoryList[uid].NotStoredFilesList = append(ui.RepositoryList[uid].NotStoredFilesList, file)
			}

		}

		/* if !hasUnstagedChanges {
			fmt.Println("没有已修改但未暂存的文件")
		} */
		/* fmt.Println("暂存区的文件:")
		//查看暂存区（已添加但未提交）的文件
		for path, fileStatus := range status {
			if fileStatus.Staging != ' ' && !fileStatus.IsUntracked() {
				fmt.Printf("暂存文件: %s, 状态: %s\n", path, fileStatus.String())
				ui.RepositoryList[uid].NotStoredFilesList = append(ui.RepositoryList[uid].NotStoredFilesList, path)
			}
		} */

		if t, ok := TreeTabData[uid]; ok {
			setTreeTab(t)
		}

		/*
			//监听文件变化
			gitWatcher, err := watcher.NewGitWatcher(TreeTabData[uid].Info.Path, 5*time.Second)
			if err != nil {
				log.Fatal(err)
			}
			gitWatcher.Watch()
		*/

	}

	tree.OnUnselected = func(id string) {
		fmt.Println("Tree node unselected:", id)
	}

	// 监听数据变化
	go func() {
		tree.Refresh()
	}()
	//默认显示首页
	if t, ok := TreeTabData["首页"]; ok {
		setTreeTab(t)
	}

	addBtn := widget.NewButton("创建", func() {})

	//搜索
	searchBtn := widget.NewButton("添加", func() {})
	// searchBtn.Icon = theme.SearchIcon()
	searchBtn.OnTapped = func() {
	}

	//刷新
	refreshBtn := widget.NewButton("克隆", func() {})
	// refreshBtn.Icon = theme.ViewRefreshIcon()
	refreshBtn.OnTapped = func() {
		dataIndex = ui.GetList()
		if t, ok := TreeTabData[ui.CurrentSelectUID]; ok {
			setTreeTab(t)
		}
		tree.Refresh()
	}

	funcUiLayout := container.NewHBox(addBtn, searchBtn, refreshBtn, widget.NewLabel(""))
	return container.NewBorder(funcUiLayout, nil, nil, nil, tree)
}

// 刷新左侧列表
func (ui *MainWindow) RefreshTree() {
	dataIndex = ui.GetList()
	fmt.Println("dataIndex:", dataIndex)
	tree.Refresh()
}

// 判断文件是否未跟踪
func isUntracked(fs *git.FileStatus) bool {
	// 未跟踪文件的条件:
	// 1. 工作树状态是Untracked
	// 2. 或者工作树有内容但暂存区是Unmodified
	return fs.Worktree == git.Untracked ||
		(fs.Worktree != git.Unmodified && fs.Staging == git.Unmodified)
}

// 文件状态检查器
func checkFileStatus(file string, fs *git.FileStatus) bool {

	/*
		状态字符含义：
		const (
			Unmodified         StatusCode = ' ' 无变化(Unmodified)
			Untracked          StatusCode = '?' 未跟踪（Untracked）
			Modified           StatusCode = 'M' 修改（Modified）
			Added              StatusCode = 'A' 新增（Added）
			Deleted            StatusCode = 'D' 删除（Deleted）
			Renamed            StatusCode = 'R' 重命名（Renamed）
			Copied             StatusCode = 'C' 复制（Copied）
			UpdatedButUnmerged StatusCode = 'U' 已更新但未合并(UpdatedButUnmerged)
		)
	*/
	//是否暂存
	isTemporarilyStore := false
	switch {

	case fs.Worktree == git.Modified && fs.Staging == git.Unmodified:
		//修改文件未暂存
		fmt.Printf("%s: 修改文件未暂存\n", file)
	case fs.Worktree == git.Untracked && fs.Staging == git.Untracked:
		//新增文件未暂存
		fmt.Printf("%s: 新增文件未暂存\n", file)
	case fs.Worktree == git.Deleted && fs.Staging == git.Unmodified:
		//删除文件未暂存
		fmt.Printf("%s: 删除文件未暂存\n", file)

	case fs.Worktree == git.Unmodified && fs.Staging == git.Modified:
		//修改文件并已暂存
		fmt.Printf("%s: 修改文件并已暂存\n", file)
		isTemporarilyStore = true
	case fs.Worktree == git.Deleted && fs.Staging == git.Added:
		//新增文件并暂存后删除
		fmt.Printf("%s: 新增文件并暂存后删除\n", file)
	case fs.Worktree == git.Unmodified && fs.Staging == git.Deleted:
		//已存在文件删除后并暂存
		fmt.Printf("%s: 已存在文件删除后并暂存\n", file)
		isTemporarilyStore = true
	}
	return isTemporarilyStore
}

// 判断是否应该忽略该文件
func shouldIgnoreFile(filename string) bool {
	// 忽略临时文件和IDE配置文件等
	ignorePatterns := []string{
		".DS_Store",
		"*.tmp",
		"*.swp",
		"*.bak",
		"*.log",
		"*.idea/",
		"*.vscode/",
	}

	for _, pattern := range ignorePatterns {
		matched, _ := filepath.Match(pattern, filename)
		if matched {
			return true
		}

		// 处理目录模式
		if strings.HasSuffix(pattern, "/") && strings.HasPrefix(filename, pattern) {
			return true
		}
	}

	return false
}

func printUnstagedChanges(worktree *git.Worktree) error {
	status, err := worktree.Status()
	if err != nil {
		return fmt.Errorf("获取状态失败: %v", err)
	}

	fmt.Println("已修改但未暂存的文件:")
	for file, fileStatus := range status {
		if fileStatus.Worktree != git.Unmodified && fileStatus.Staging == git.Unmodified {
			var changeType string
			switch fileStatus.Worktree {
			case git.Modified:
				changeType = "修改"
			case git.Added:
				changeType = "新增"
			case git.Deleted:
				changeType = "删除"
			case git.Renamed:
				changeType = "重命名"
			case git.Copied:
				changeType = "复制"
			case git.UpdatedButUnmerged:
				changeType = "更新但未合并"
			default:
				changeType = string(fileStatus.Worktree)
			}
			fmt.Printf("%-10s %s\n", changeType, file)
		}
	}
	return nil
}

// 左侧列表
func (ui *MainWindow) GetList() map[string][]string {
	//列表索引(用于显示左侧列表)
	dataListIndex := make(map[string][]string)

	lists := ui.Services.GetProject()
	//一级列表
	var firstLevelList []string
	firstLevelList = append(firstLevelList, "首页")
	for _, v := range lists {
		firstLevelList = append(firstLevelList, v.Name)
	}
	dataListIndex[""] = firstLevelList

	TreeTabData["首页"] = services.TreeTabInfo{Info: models.Project{Id: 0, Name: "首页"}, View: ui.welcomeScreen}

	for _, v := range lists {
		// 使用函数工厂
		makeRepositoryUiFunc := ui.createRepositoryViewFunc(v.Name)
		TreeTabData[v.Name] = services.TreeTabInfo{Info: v, View: makeRepositoryUiFunc}

		//打开本地git项目
		// repo, err := git.PlainOpen(v.Path)
		// 正确打开仓库的方式：
		repo, err := git.PlainOpenWithOptions(v.Path, &git.PlainOpenOptions{
			DetectDotGit: true, // 自动检测 .git 目录（适用于工作树或裸仓库）
		})
		if err != nil {
			log.Println("无法打开本地git项目:", err)
			log.Fatal(err)
		}
		if ui.RepositoryList == nil {
			ui.RepositoryList = make(map[string]*RepositoryInfo)
		}
		//放到git仓库列表中
		ui.RepositoryList[v.Name] = &RepositoryInfo{Repo: repo}
	}

	return dataListIndex
}

// 独立的视图创建函数
func (ui *MainWindow) createRepositoryViewFunc(name string) func(fyne.Window) fyne.CanvasObject {
	return func(w fyne.Window) fyne.CanvasObject {
		return ui.MakeRepositoryUI(w, name)
	}
}
